오늘의 탐구생활. 요즘 만짓만짓하는 코드를 나중에 팀에 설명하려면 어디서부터 이야기를 해야 하나 멍때리다가 한 꼭지만 생각을 정리해 본다.
전역변수 a[3][64*100] 이 있다.
멀티쓰레드 코딩을 하면 첫번째 차원(3)의 인덱싱으로 각 코어가 접근하도록 하면 비용 낭비가 없다. 락도 없다. COW도 없다.
전역변수 int a[3][2]이 있다.
각 코어가 a[n][1]을 접근하면 거짓 공유가 발생한다.
현대 CPU 아키텍처에서 캐시라인은 64바이트다.
전역 변수 a는 한 덩어리가 64바이트 보다 작다.
각 코어가 a를 참조할 때 캐시가 깨져서 매번 캐시로 다시 가져온다.
2소켓 NUMA 상황이다.
멀티스레드 등에서 사용할 코어 번호를 지정해서 각 a[0] a[1] .. 에 쓰기를 하는 순간 COW처럼 자기 소켓의 주소로 붙는다.
이러면 속도도 빠를 뿐만 아니라 거짓 공유도 발생하지 않는다. 하지만 NUMA를 제대로 쓰는 것은 까다롭다.
C/리눅스/멀티프로세스다.
대형 전역 변수 a를 셋팅한 후 포킹했다.
각 코어는 읽기만 한다.
a는 복제되지 않고 모든 코어가 공유해서 쓴다.
빠르다.
포킹한 프로세스에서 뭔가 쓰기를 했다.
COW가 발동하며 그 지점의 페이지를 복사한다.
복사 비용이 든다.
C/리눅스/멀티쓰레드다.
락을 논외로하면 전역변수는 복제없이 동작한다.
일부 쓰기 작업이 있을시 거짓 공유 정도만 회피하면 낭비 지점이 별로 없다.
파이썬/리눅스/멀티쓰레드다.
전역변수 접근 비용은 마찬가지로 적다. 그러나 GIL의 저주는 현재 통용 버전에서 해소되지 않았다. 멀티쓰레드라면서 1코어만 쓴다.
게다가 각 쓰레드가 접근할 때마다 refcount의 동시성 유지를 위해서도 GIL이 동원 될 것이다.
사실은 GC등을 위해서도 이것저것 만질 것이다.
파이썬/리눅스/멀티프로세스다.
전역변수 읽기만 접근해도 refcount변경을 위해 COW가 발생한다.
GIL은 발생하지 않는다. C코드 대비 COW 비용은 든다.